import re
import pefile
import tkinter as tk
from tkinter import scrolledtext, messagebox, filedialog

def parse_node_func_names(code):
    # 匹配 "xxx:" 开头的函数名
    funcs = re.findall(r"(\w+)\s*:", code)
    node_func_names = []
    for f in funcs:
        node_func_names.append(f)
    return node_func_names

def parse_dll_func_names(dll_path):
    try:
        pe = pefile.PE(dll_path)
        dll_func_names = []
        if hasattr(pe, "DIRECTORY_ENTRY_EXPORT"):
            for exp in pe.DIRECTORY_ENTRY_EXPORT.symbols:
                if exp.name:
                    name = exp.name.decode("utf-8")
                    # 过滤掉以下划线开头的函数
                    if not name.startswith("?"):
                        dll_func_names.append(name)
                else:
                    dll_func_names.append(f"ordinal_{exp.ordinal}")  # 没名字的用序号代替
        return dll_func_names
    except Exception as e:
        messagebox.showerror("Error", f"Failed to parse DLL: {str(e)}")
        return []

def diff_func_names(code, dll_path):
    node_func_names = parse_node_func_names(code)
    dll_func_names = parse_dll_func_names(dll_path)
    return list(set(node_func_names) - set(dll_func_names))

def run_comparison():
    code = code_text.get("1.0", tk.END).strip()
    dll_path = path_entry.get().strip()
    if not code or not dll_path:
        messagebox.showwarning("Input Error", "Please provide both code and DLL path")
        return
    result = diff_func_names(code, dll_path)
    result_text.delete("1.0", tk.END)
    if result:
        result_text.insert(tk.END, "\n".join(result))
    else:
        result_text.insert(tk.END, "No differences found or error occurred")

def browse_file():
    file_path = filedialog.askopenfilename(
        initialdir=r"D:/kl-storage/dll",
        filetypes=[("DLL files", "*.dll"), ("All files", "*.*")]
    )
    if file_path:
        path_entry.delete(0, tk.END)
        path_entry.insert(0, file_path)

# Create main window
root = tk.Tk()
root.title("DLL函数侦测小工具V1.0(xuyax)")
root.geometry("800x600")

# Create two main frames for left and right columns
left_frame = tk.Frame(root)
left_frame.pack(side=tk.LEFT, padx=10, pady=10, fill=tk.BOTH, expand=True)
right_frame = tk.Frame(root)
right_frame.pack(side=tk.RIGHT, padx=10, pady=10, fill=tk.BOTH, expand=True)

# Left column: Code input and DLL path input
tk.Label(left_frame, text="Enter Code:").pack(anchor="nw")
code_text = scrolledtext.ScrolledText(left_frame, height=20, width=50)
code_text.pack(pady=5, fill=tk.BOTH, expand=True)
code_text.insert(tk.END, '''calculateChipsCoorV2: [ 'int', [ // 'string', 'int', 'string', 'int', 'int', 'int', 'string', 'string', 'double*', 'double*', 'double*', 'double*', 'double*', 'int', 'double*', 'string', 'int', 'double', 'int', 'int*', 'double**', ], ],
calculateChipsCoorV2_Offline: [ 'int', [ // 'string', 'int', 'string', 'int', 'int', 'int', 'string', 'string', 'double*', 'double*', 'double*', 'double*', 'double*', 'int', 'double*', 'string', 'int', 'double', 'int', 'int*', 'double**', ], ],
releaseAllCache: ['void', []],
releaseArray: ['void', ['double **']],
get_dll_version: ['string', []],''')

# DLL path input with browse button
path_frame = tk.Frame(left_frame)
path_frame.pack(fill=tk.X, pady=5)
tk.Label(path_frame, text="DLL Path:").pack(side=tk.LEFT, anchor="nw")
path_entry = tk.Entry(path_frame, width=40)
path_entry.pack(side=tk.LEFT, fill=tk.X, expand=True)
path_entry.insert(0, r"D:\kl-storage\dll\wafer.dll")
tk.Button(path_frame, text="Browse", command=browse_file).pack(side=tk.LEFT, padx=5)

run_button = tk.Button(left_frame, text="Compare Functions", command=run_comparison)
run_button.pack(pady=10)

# Right column: Results output
tk.Label(right_frame, text="Results:").pack(anchor="nw")
result_text = scrolledtext.ScrolledText(right_frame, height=20, width=50)
result_text.pack(pady=5, fill=tk.BOTH, expand=True)

# Start the main loop
root.mainloop()